package com.xinmao.quantitative;

import cn.hutool.core.date.DateUtil;
import com.xinmao.quantitative.chart.DataFlowToChart;
import com.xinmao.quantitative.constant.Constants;
import com.xinmao.quantitative.enums.EastMoneyAdjustEnum;
import com.xinmao.quantitative.enums.EastMoneyPeriodEnum;
import com.xinmao.quantitative.enums.GridTansType;
import com.xinmao.quantitative.model.GridModel;
import com.xinmao.quantitative.trad.strategies.grid.GridTradingStrategy;
import com.xinmao.quantitative.trad.strategies.grid.GridTradingStrategy2;
import com.xinmao.quantitative.utils.Components;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.ta4j.core.BarSeries;
import org.ta4j.core.Position;
import org.ta4j.core.Trade;
import org.ta4j.core.analysis.cost.CostModel;
import org.ta4j.core.analysis.cost.LinearTransactionCostModel;
import org.ta4j.core.indicators.UlcerIndexIndicator;
import org.ta4j.core.indicators.helpers.*;
import org.ta4j.core.num.DecimalNum;
import org.ta4j.core.num.Num;

import java.util.*;

@SpringBootTest
@Slf4j
public class GridTradingTest2 {

    @Autowired
    private Components components;
    @Autowired
    private GridTradingStrategy2 gridTradingStrategy2;



    @Test
    public void test2() {
        //获取前20个交易日
        int barCount = 20;
        String symbol = "159740";
        CostModel costModel = new LinearTransactionCostModel(0.0001);
        Num buyNum = DecimalNum.valueOf(2000);

//        String now = DateUtil.format(new Date(), Constants.DATE_FORMAT_SIMPLE);
//        BarSeries seriesDay = components.loadFundBarData(symbol, "20240101", now);
//        String startDate = seriesDay.getBar(seriesDay.getEndIndex() - barCount).getEndTime().format(Constants.DATE_FORMAT_SIMPLE);
//        BarSeries series = components.loadFundBarDataMin(symbol, startDate, now, EastMoneyAdjustEnum.HFQ.getType(), EastMoneyPeriodEnum.MIN_5.getType());

        BarSeries series = components.loadBarData1Min(symbol);

        BarSeries subSeries = series.getSubSeries( series.getBarCount()/2, series.getEndIndex());


        HighPriceIndicator highPrice = new HighPriceIndicator(subSeries);
        LowPriceIndicator lowPrice = new LowPriceIndicator(subSeries);

        Num highestHighPrice = new HighestValueIndicator(highPrice, subSeries.getBarCount()).getValue(subSeries.getEndIndex());
        Num lowestLowPrice = new LowestValueIndicator(lowPrice, subSeries.getBarCount()).getValue(subSeries.getEndIndex());

        GridModel gridModel = GridModel.builder()
                .lowPrice(lowestLowPrice)
                .upPrice(highestHighPrice)
                .byAmount(DecimalNum.valueOf(0.003))
                .costModel(costModel)
                .buyNum(buyNum)
                .maxHoldNum(DecimalNum.valueOf(10000))
                .gridTansType(GridTansType.PRICE)
                .build();


        List<Trade> trades = gridTradingStrategy2.getTradeByPrice(gridModel,subSeries);
        List<Trade> buys = new ArrayList<>(trades.stream().filter(trade -> trade.getType().equals(Trade.TradeType.BUY)).toList());
        List<Trade> sells = trades.stream().filter(trade -> trade.getType().equals(Trade.TradeType.SELL)).toList();

        List<Position> positions = new ArrayList<>();
        for (Trade s : sells) {
            buys.stream().filter(buy -> buy.getIndex() < s.getIndex()).min(Comparator.comparing(Trade::getPricePerAsset)).ifPresent(buy -> {
                positions.add(new Position(buy, s));
                buys.remove(buy);
            });
        }
        Num grossProfit = positions.stream().map(Position::getGrossProfit).reduce(subSeries.zero(), Num::plus);
        Num profit = positions.stream().map(Position::getProfit).reduce(subSeries.zero(), Num::plus);
        Num grossReturn = positions.stream().map(Position::getGrossReturn).reduce(subSeries.zero(), Num::plus);

        positions.forEach(position -> {
            log.info("{},{}", subSeries.getBar(position.getEntry().getIndex()).getEndTime().format(Constants.DATE_TIME_FORMAT), position);
        });
        log.info("参考价格时间段：{}--{}", subSeries.getBar(subSeries.getBeginIndex()).getEndTime().format(Constants.DATE_TIME_FORMAT), subSeries.getBar(subSeries.getEndIndex()).getEndTime().format(Constants.DATE_TIME_FORMAT));
        System.out.println("净利润：" + profit + " 总利润：" + grossProfit + " 利润率%：" + grossReturn);
        System.out.println("剩余：" + buys.size() + " 交易次数 ：" + trades.size()+" 成本占用："
                + subSeries.getBar(subSeries.getEndIndex()).getClosePrice().multipliedBy(DecimalNum.valueOf(buys.size())).multipliedBy(gridModel.getBuyNum()));
        System.out.println("价格区间：" + gridModel.getUpPrice() + "--" + gridModel.getLowPrice() + " 价格区间差：" + gridModel.getUpPrice().minus(gridModel.getLowPrice()));
    }
}